package com.tianyadu.security.browser.conf;

import com.tianyadu.security.core.authentication.AbstractChannelSecurityConfig;
import com.tianyadu.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
import com.tianyadu.security.core.properties.SecurityProperties;
import com.tianyadu.security.core.properties.propertieVO.SecurityConstants;
import com.tianyadu.security.core.validate.code.conf.ValidateCodeSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.sql.DataSource;

/**
 * @FileName: BrowserSecurityConfig
 * @Description: springSecurity适配器自定义
 * @author: xueyj
 * @create: 2018-12-05 22:51
 */
@Configuration
public class BrowserSecurityConfig extends AbstractChannelSecurityConfig {
    /** 获取security配置信息 */
    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;

    @Autowired
    private SpringSocialConfigurer tianyaduSocialSecurityConfig;

    /** 申明密码加密方式 */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * 记住我功能的token存取器配置
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        //  初始化数据库需要设置
		// tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //  用户名密码登陆相关配置（登陆页面，验证成功/失败处理器）
        applyPasswordAuthenticationConfig(http);

        http.apply(validateCodeSecurityConfig)
                .and()
             .apply(smsCodeAuthenticationSecurityConfig)
                .and()
             .apply(tianyaduSocialSecurityConfig)
                .and()
             .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
                .userDetailsService(userDetailsService)
                .and()
                .authorizeRequests()
             .antMatchers(
                        SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                        SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
                        securityProperties.getBrowser().getLoginPage(),
                        SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+"/*",
                     securityProperties.getBrowser().getSignUpUrl(),
                     "/user/regist")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
       /* //  初始化code拦截器
        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
        //  设置校验失败处理器
        validateCodeFilter.setAuthFailureHandler(authFailureHandler);
        //  设置校验配置项信息
        validateCodeFilter.setSecurityProperties(securityProperties);
        //  初始化校验拦截
        validateCodeFilter.afterPropertiesSet();
        //  登陆页信息
        String loginPage = securityProperties.getBrowser().getLoginPage();
        //  记住我token过期时间
        int rememberMeSeconds = securityProperties.getBrowser().getRememberMeSeconds();
        *//**
         指定身份认证方式，所有请求都需要授权认证
         addFilterBefore:添加自定义过滤器，在XXX过滤器之前
         认证方式一：http.formLogin() 表单登陆认证
         认证方式二: http.httpBasic() httpBasic登陆认证
         loginPage("XXX.html"): 登陆页面
         loginProcessingUrl: 登陆处理url
         successHandler：成功处理器
         failureHandler：失败处理器
         and()：权限认证关联条件
         authorizeRequests()：请求授权信息
         antMatchers("/XXX.html").permitAll()：当前匹配路径跳过认证
         anyRequest()：任何请求信息
         authenticated()：需要身份认证
         *//*
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage("/authentication/require")
                .loginProcessingUrl("/authentication/form")
                .successHandler(authSuccessHandler)
                .failureHandler(authFailureHandler)
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(rememberMeSeconds)
                .userDetailsService(userDetailsService)
                .and()
                .authorizeRequests()
                .antMatchers("/authentication/require",loginPage, "/code/*").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable()
                .apply(smsCodeAuthenticationSecurityConfig);*/
    }
}